package com.sdgs.paas.sdk.core.metrics;

import static com.sdgs.paas.sdk.core.metrics.PaasMethodMetricsEnum.ARGS;
import static com.sdgs.paas.sdk.core.metrics.PaasMethodMetricsEnum.DURATION;
import static com.sdgs.paas.sdk.core.metrics.PaasMethodMetricsEnum.ENDTIME;
import static com.sdgs.paas.sdk.core.metrics.PaasMethodMetricsEnum.KEY;
import static com.sdgs.paas.sdk.core.metrics.PaasMethodMetricsEnum.STARTTIME;
import static com.sdgs.paas.sdk.core.utils.DateUtils.transferLongToDate;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.util.StringUtils;

import com.sdgs.paas.sdk.core.IPaasParam;
import com.sdgs.paas.sdk.core.log.PaasLogger;

/**
 * 指标收集切面类
 *
 * @author wjj
 *
 */
@Aspect
public class PaasMethodMetricsAspect {

	ThreadLocal<Map<Enum<PaasMethodMetricsEnum>, String>> span = new ThreadLocal<Map<Enum<PaasMethodMetricsEnum>, String>>();

	@Pointcut("@within(com.sdgs.paas.sdk.core.RefreshableRestController)")
	public void annotationPointCut() {
	}

	@Before("annotationPointCut()")
	public void collectBefore(JoinPoint jp) {
		long st = System.currentTimeMillis();
		String key = new StringBuilder().append(jp.getSignature().getDeclaringTypeName()).append(".")
				.append(jp.getSignature().getName()).toString();
		List<String> newArgs = Arrays.asList(jp.getArgs()).stream().map(e -> {
			if (e == null) {
				return "null";
			} else if (e instanceof IPaasParam) {
				return ((IPaasParam) e).paramInfo();
			} else {
				return e.toString();
			}
		}).collect(Collectors.toList());
		String argstr = StringUtils.collectionToCommaDelimitedString(newArgs);
		String begin = Long.toString(st);
		PaasLogger.metricInfo("采集指标开始！方法名:{},参数:{},起始时间:{}", key, argstr, transferLongToDate(begin));

		Map<Enum<PaasMethodMetricsEnum>, String> metricsMap = new HashMap<Enum<PaasMethodMetricsEnum>, String>();
		span.set(metricsMap);
		span.get().put(KEY, key);
		span.get().put(ARGS, argstr);
		span.get().put(STARTTIME, begin);
	}

	@After("annotationPointCut()")
	public void collectAfter(JoinPoint jp) {

		long et = System.currentTimeMillis();
		span.get().put(ENDTIME, Long.toString(et));
		span.get().put(DURATION, Long.toString(et - Long.valueOf(span.get().get(STARTTIME))));
		// span.get().put(SUCCESS, "true");
		PaasLogger.metricInfo("采集指标结束！方法名:{},参数:{},起始时间:{},结束时间:{},耗时:{}", span.get().get(KEY), span.get().get(ARGS),
				transferLongToDate(span.get().get(STARTTIME)), transferLongToDate(span.get().get(ENDTIME)),
				span.get().get(DURATION));
	}

	// @AfterReturning(value = "annotationPointCut()", returning = "obj")
	// public void collectAfterReturning(JoinPoint jp, Object obj) {
	//
	// if ("true".equals(smartBssEndpointConfig.getSmartbssmetrics())) {
	// span.get().put(SUCCESS, Boolean.toString(((ISmartBssMetrics)
	// obj).isSuccess()));
	// }
	// PaasLogger.info("采集是否成功指标结束！");
	// }

	@AfterThrowing(value = "annotationPointCut()", throwing = "obj")
	public void collectAfterThrowing(JoinPoint jp, Throwable obj) {

		// span.get().put(SUCCESS, "false");
		PaasLogger.metricError(obj, "采集指标结束！方法抛出异常！方法名:{},参数:{},起始时间:{},结束时间:{},耗时:{}", span.get().get(KEY),
				span.get().get(ARGS), transferLongToDate(span.get().get(STARTTIME)),
				transferLongToDate(span.get().get(ENDTIME)), span.get().get(DURATION));
	}

}